﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;

namespace Master
{
    class TwoWayTrafficLightStrategy : iTrafficLightStrategy
    {
        /*************
         * VARIABLES *
         *************/
        private Thread strategyThread;
        private List<Lane> lanes;

        /********************
         * PUBLIC FUNCTIONS *
         ********************/
        public void start(Dictionary<Side, List<Road>> roadDictionary)
        {
            lanes = new List<Lane>();
            foreach (List<Road> sublist in roadDictionary.Values)
                foreach (Road road in sublist)
                    foreach (Lane lane in road.getLanes())
                        if (lane.hasTrafficLight())
                            lanes.Add(lane);
            strategyThread = new Thread(handleTraffic);
            strategyThread.Start();

        }

        public void stop()
        {
            strategyThread.Abort();
        }

        /*********************
         * PRIVATE FUNCTIONS *
         *********************/

        private List<Lane> getCurrentLanes(Boolean horizontal)
        {
            List<Lane> currentLanes = new List<Lane>();
            foreach (Lane lane in lanes)
            {
                int orientation = 0;
                lane.trafficLight.Dispatcher.Invoke(new Action(delegate() { orientation = lane.Orientation; }));
                if ((horizontal == true && (orientation == 0 || orientation == 180)) || (horizontal == false && (orientation == 90 || orientation == 270)))
                    currentLanes.Add(lane);
            }
            return currentLanes;
        }

        private void setStatus(List<Lane> currentLanes, TrafficLightStatus newStatus, int sleepTime)
        {
            foreach (Lane lane in currentLanes)
                lane.Dispatcher.Invoke(
                        new Action(delegate() { lane.trafficLight.SetValue(TrafficLight.statusProperty, newStatus); })
                        );
            Thread.Sleep(sleepTime);
        }

        private void handleTraffic()
        {
            try
            {
                Boolean horizontal = true;
                while (true)
                {
                    List<Lane> currentLanes = getCurrentLanes(horizontal);
                    setStatus(currentLanes, TrafficLightStatus.GREEN, 3000);
                    setStatus(currentLanes, TrafficLightStatus.ORANGE, 2000);
                    setStatus(currentLanes, TrafficLightStatus.RED, 250);
                    horizontal = !horizontal;
                }
            }
            catch (ThreadAbortException e)
            {
                Trace.WriteLine("Thread was aborted by: " + e.GetType());
                return;
            }
        }
    }

}
